package com.zwh.se.io.nio.channel;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author zwh
 * 通道（Channel):
 * NIO 的通道类似于流，但有些区别如下：
 * 通道可以同时进行读写，而流只能读或者只能写
 * 通道可以实现异步读写数据
 * 通道可以从缓冲读数据，也可以写数据到缓冲:
 * BIO 中的 Stream 是单向的，例如 FileInputStream 对象只能进行读取数据的操作，而 NIO 中的通道（Channel）是双向的，可以读操作，也可以写操作。
 * Channel 在 NIO 中是一个接口 public interface Channel extends Closeable{}
 * 常用的 Channel 类有：FileChannel、DatagramChannel、ServerSocketChannel 和 SocketChannel。【ServerSocketChanne 类似 ServerSocket、SocketChannel 类似 Socket】
 * FileChannel 用于文件的数据读写，DatagramChannel 用于 UDP 的数据读写，ServerSocketChannel 和 SocketChannel 用于 TCP 的数据读写
 */
public class ChannelDemo {
        //transferFrom 从目标通道中复制数据到当前通道
        //transferTo 把数据从当前通道复制给目标通道
        public static void main(String[] args) throws Exception {
                String str = "hello";
                //创建一个输入\输出流 -> channel
                FileInputStream fileInputStream = new FileInputStream("file/input.txt");
                FileOutputStream fileOutputStream = new FileOutputStream("file/output.txt");

                //获取对应的 FileChannel
                //这个 fileChannel 真实类型是 FileChannelImpl
                FileChannel outputChannel = fileOutputStream.getChannel();
                FileChannel inputChannel = fileInputStream.getChannel();
                //使用 transferForm 完成拷贝
                //outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
                //创建一个缓冲区 ByteBuffer
                ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                int read;
                //循环读取
                while (true){
                        //清空缓冲区
                        byteBuffer.clear();

                        //将读取的数据放入 byteBuffer
                        if((read = inputChannel.read(byteBuffer)) != -1){
                                //对 byteBuffer 进行 flip
                                byteBuffer.flip();
                                //将 byteBuffer 数据写入到 fileChannel
                                outputChannel.write(byteBuffer);
                        }else {
                                break;
                        }
                }
                outputChannel.close();
                inputChannel.close();
                fileOutputStream.close();
                fileInputStream.close();
        }
}

